# -*- coding:utf-8 -*-

from __future__ import unicode_literals
from __future__ import print_function

from argparse import ArgumentParser

from kgpipeline.util import load_json, load_pickle


def show_type(index, type_name, types, slinks):
    type_hierarchy = types[type_name]

    if type_name in slinks:
        type_class = "thin link"
    elif "CnsLink" in type_hierarchy:
        type_class = "fat link"
    elif "DataType" in type_hierarchy:
        type_class = "data type"
    elif "CnsDataStructure" in type_hierarchy:
        type_class = "data structure"
    else:
        type_class = "entity"

    if len(type_hierarchy) == 1:
        print("{0}) {1} ({2})".format(index, type_name, type_class))
    else:
        print("{0}) {1} ({2}) < {3}".format(index, type_name, type_class, " < ".join(type_hierarchy[1:])))


def show_one(index, type_name, types, slinks, plist, no_properties=False):
    show_type(index, type_name, types, slinks)

    if not no_properties and type_name in plist:
        props = plist[type_name]
        keys = props.keys()
        if keys:
            max_len = max([len(k) for k in keys]) + 2
            for i, key in enumerate(sorted(keys)):
                range_type = props[key]["range"]
                alt = props[key]["alt"]
                if alt:
                    print("  {0:3d}] ({1:8s}) {2}: {3}".format(i+1, range_type, key.ljust(max_len), "|".join(alt)))
                else:
                    print("  {0:3d}] ({1:8s}) {2}".format(i+1, range_type, key))


def show_header(schema_name, no_properties=False):
    if no_properties:
        last_part = ""
    else:
        last_part = " and Properties"
    header = "{0} Types{1}".format(schema_name, last_part)
    header_len = len(header)
    print("="*header_len)
    print(header)
    print("="*header_len)


def show_schema(schema, name=None, no_properties=False):
    types = schema["types"]
    plist = schema["plist"]
    slinks = schema["slinks"]
    schema_name = schema["name"]

    show_header(schema_name, no_properties)

    if name is not None:
        show_one(1, name, types, slinks, plist, no_properties)
    else:
        for i, cns_type in enumerate(sorted(schema["types"].keys())):
            show_one(i+1, cns_type, types, slinks, plist, no_properties)


def main(schema_file, name=None, no_properties=False):
    if schema_file.endswith('.json'):
        schema = load_json(schema_file)
    else:
        schema = load_pickle(schema_file)
    show_schema(schema, name, no_properties)


if __name__ == '__main__':
    parser = ArgumentParser(description="show schema file content")
    parser.add_argument("-c", "--cns-type", help="only show this specified type")
    parser.add_argument("-n", "--no-properties", action='store_true', help="do not show properties")
    parser.add_argument("schema", help="the schema file, `.json` in json format or `.pkl` in pickle format")

    args = parser.parse_args()

    main(args.schema, args.cns_type, args.no_properties)
